#include "mempool.h"
#include <cstddef>
#include <cstdlib>
#include <cstring>
#include <new>

MemoryPool::MemoryPool(size_t blockSize, size_t blockCount)
: memory(nullptr), freeList(nullptr), blockSize(blockSize), blockCount(blockCount){
    if (blockSize < sizeof(void*)) {
        blockSize = sizeof(void*);
    }

    size_t totalSize = blockSize * blockCount;
    memory = std::malloc(totalSize);
    if (!memory) {
        throw std::bad_alloc();
    }

    initFreeList();
}

void MemoryPool::initFreeList(){
    char* current = static_cast<char*>(memory);
    for (size_t i = 0; i < blockCount; i++) {
        void* next = (i == blockCount - 1) ? nullptr : (current + blockSize);
        memcpy(current, &next, sizeof(void*));
        current += blockSize;
    }
    freeList = memory;
}

void* MemoryPool::allocate(){
    if (!freeList) {
        return nullptr;
    }

    void* block = freeList;
    memcpy(&freeList, block, sizeof(void*));
    return block;
}

void MemoryPool::deallocate(void* ptr){
    if (!ptr) {
        return;
    }

    memcpy(ptr, &freeList, sizeof(void*));
    freeList = ptr;
}

MemoryPool::~MemoryPool(){
    free(memory);
}